package ice.server.comm;

import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * JPSQLModel 模型快速创建工具类，支持流式API
 *
 * @author zhangrb
 * @user all
 * @date 2019-8-22
 */
public class JPSQLModelBuilder {

    /**
     * 初始JPSQLModel对象
     */
    private JPSQLModel jPSQLModel = new JPSQLModel();

    // 当前的关联实体
    private JPSQLModel.EntityJoin currentEntityJoin;

    /**
     * 创建一个build实例
     * @author zhangrb
     * @user zhangrb
     * @date 2019-8-2
     * @return 构建对象
     */
    public static JPSQLModelBuilder build() {
        return new JPSQLModelBuilder();
    }

    /**
     * 创建查询实体
     * @param entityClass 实体对应的class
     * @param alias 查询实体的别名，别名在构建查询结果字段、查询条件、分组、having、排序时有用
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-22
     * @return 新创建的查询实体对象
     */
    private JPSQLModel.QueryEntity createQueryEntity(Class<?> entityClass, String alias) {
        JPSQLModel.QueryEntity qe = new JPSQLModel.QueryEntity();
        qe.setEntityClass(entityClass);
        qe.setAlias(alias);
        return qe;
    }

    /**
     * 构建from模块
     * @param entityClass 实体类型的class
     * @param alias 实体的别名，别名在构建查询结果字段、查询条件、分组、having、排序时有用
     * @author zhangrb
     * @user all
     * @date 2019-08-22
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder from(Class<?> entityClass, String alias) {
        if(jPSQLModel.getRootEntity() != null) {
            throw new JPQLModelException("当前存在一个以上from语句，只能存在一个from语句");
        }
        JPSQLModel.QueryEntity qe = createQueryEntity(entityClass, alias);
        jPSQLModel.setRootEntity(qe);
        return this;
    }

    /**
     * 构建实体内关联
     * @param entityClass 要关联的实体的class
     * @param alias 要关联的实体别名，别名在构建查询结果字段、查询条件、分组、having、排序时有用
     * @author zhangrb
     * @user all
     * @date 2019-08-22
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder join(Class<?> entityClass, String alias) {
        makeJoin(entityClass, alias, JPSQLModel.JoinType.INNER_JOIN);
        return this;
    }

    /**
     * 构建实体左关联
     * @param entityClass 要关联的实体的class
     * @param alias 要关联的实体别名，别名在构建查询结果字段、查询条件、分组、having、排序时有用
     * @author zhangrb
     * @user all
     * @date 2019-08-22
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder leftJoin(Class<?> entityClass, String alias) {
        makeJoin(entityClass, alias, JPSQLModel.JoinType.LEFT_JOIN);
        return this;
    }

    /**
     * 构建实体右关联
     * @param entityClass 要关联的实体的class
     * @param alias 要关联的实体别名，别名在构建查询结果字段、查询条件、分组、having、排序时有用
     * @author zhangrb
     * @user all
     * @date 2019-08-22
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder rightJoin(Class<?> entityClass, String alias) {
        makeJoin(entityClass, alias, JPSQLModel.JoinType.RIGHT_JOIN);
        return this;
    }

    /**
     * 构建实体关联
     * @param entityClass 要关联的实体的class
     * @param alias 要关联的实体别名，别名在构建查询结果字段、查询条件、分组、having、排序时有用
     * @param jt 连接类型
     * @author zhangrb
     * @user all
     * @date 2019-08-22
     * @return 构建器本身，以便支持流式调用
     */
    private void makeJoin(Class<?> entityClass, String alias, JPSQLModel.JoinType jt) {
        if(jPSQLModel.getRootEntity() == null) {
            throw new JPQLModelException("当前不存在from语句，无法使用join语句");
        }
        JPSQLModel.EntityJoin ej = new JPSQLModel.EntityJoin();
        JPSQLModel.QueryEntity qe = createQueryEntity(entityClass, alias);
        ej.setEntity(qe);
        ej.setJoinType(jt);
        if (currentEntityJoin == null) {
            jPSQLModel.setEntityJoin(ej);
        } else {
            currentEntityJoin.setNextEntityJoin(ej);
        }
        currentEntityJoin = ej;
    }

    /**
     * 构建on语句，应该在使用连接语句后立即使用on语句，且只能使用一次on语句
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder on() {
        if (currentEntityJoin == null) {
            throw new JPQLModelException("没有关联表，无法使用on语句");
        }
        if (!currentEntityJoin.getJoinCondtions().isEmpty()) {
            throw new JPQLModelException("已经存在一个on语句，如果想使用or逻辑请使用or_on语句");
        }
        JPSQLModel.JoinCondtion jc = new JPSQLModel.JoinCondtion();
        currentEntityJoin.getJoinCondtions().add(jc);
        return this;
    }

    /**
     * 构建on语句中or语句，必须保证当前关联实体已经存在了一个on语句
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder or_on() {
        if (currentEntityJoin == null) {
            throw new JPQLModelException("没有关联表，无法使用on语句");
        }
        if (currentEntityJoin.getJoinCondtions().isEmpty()) {
            throw new JPQLModelException("当前不存在on语句，请使用on语句");
        }
        JPSQLModel.JoinCondtion jc = new JPSQLModel.JoinCondtion();
        currentEntityJoin.getJoinCondtions().add(jc);
        return this;
    }

    /**
     * 添加‘=’的关联条件
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addJoinParamForEq(String leftProperty, String rightProperty) {
        addJoinParam(leftProperty, null, rightProperty);
        return this;
    }

    /**
     * 添加‘！=’的关联条件
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addJoinParamForNotEq(String leftProperty, String rightProperty) {
        addJoinParam(leftProperty, Constants.NE_SF, rightProperty);
        return this;
    }

    /**
     * 添加‘>=’的关联条件
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addJoinParamForGe(String leftProperty, String rightProperty) {
        addJoinParam(leftProperty, Constants.GE_SF, rightProperty);
        return this;
    }

    /**
     * 添加‘>’的关联条件
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addJoinParamForGt(String leftProperty, String rightProperty) {
        addJoinParam(leftProperty, Constants.GT_SF, rightProperty);
        return this;
    }

    /**
     * 添加‘<’的关联条件
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addJoinParamForLt(String leftProperty, String rightProperty) {
        addJoinParam(leftProperty, Constants.LT_SF, rightProperty);
        return this;
    }

    /**
     * 添加‘<=’的关联条件
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addJoinParamForLe(String leftProperty, String rightProperty) {
        addJoinParam(leftProperty, Constants.LE_SF, rightProperty);
        return this;
    }

    /**
     * 添加关联条件的工具方法
     * @param leftProperty 关联条件的左侧字段
     * @param rightProperty 关联条件的右侧字段
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    private void addJoinParam(String leftProperty, String op, String rightProperty) {
        if (currentEntityJoin == null) {
            throw new JPQLModelException("没有关联表，无法添加关联条件");
        }
        if (currentEntityJoin.getJoinCondtions().isEmpty()) {
            throw new JPQLModelException("当前不存在on语句或or_on语句，无法添加连接条件");
        }
        Map<String, String> pm = currentEntityJoin.getJoinCondtions().get(currentEntityJoin.getJoinCondtions().size() - 1).getJoinParam();
        op = StringUtils.isEmpty(op) ? "" : op;
        pm.put(leftProperty + op, rightProperty);
    }

    /**
     * 添加查询结果字段对象
     * @param name 字段名称
     * @param alias 字段别名
     * @param funcType 聚合函数类型
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addQueryProperty(String name, String alias, JPSQLModel.FunctionType funcType) {
        JPSQLModel.QueryProperty qp = new JPSQLModel.QueryProperty();
        qp.setName(name);
        qp.setAlias(alias);
        qp.setFuncType(funcType);
        jPSQLModel.getResult().add(qp);
        return this;
    }

    /**
     * 添加查询结果字段对象
     * @param name 字段名称
     * @param alias 字段别名
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addQueryProperty(String name, String alias) {
        JPSQLModel.QueryProperty qp = new JPSQLModel.QueryProperty();
        qp.setName(name);
        qp.setAlias(alias);
        qp.setFuncType(null);
        jPSQLModel.getResult().add(qp);
        return this;
    }

    /**
     * 构建查询条件语句，只能存在一个condition语句
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder condition() {
        if(!jPSQLModel.getQueryConditions().isEmpty()) {
            throw new JPQLModelException("已经存在一个condition语句， 如果你想使用or逻辑， 请使用or_condition()语句");
        }
        JPSQLModel.QueryCondition qc = new JPSQLModel.QueryCondition();
        jPSQLModel.getQueryConditions().add(qc);
        return this;
    }

    /**
     * 构建查询条件语句中的or语句，必须保证当前语句中已经存在了一个condition语句
     * @author zhangrb
     * @user zhangrb
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder or_condition() {
        if(jPSQLModel.getQueryConditions().isEmpty()) {
            throw new JPQLModelException("当前没有condition语句， 无法使用or_condition()语句");
        }
        JPSQLModel.QueryCondition qc = new JPSQLModel.QueryCondition();
        jPSQLModel.getQueryConditions().add(qc);
        return this;
    }

    /**
     * 添加‘=’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForEq(String property, Object value) {
        addConditionParam(property, null, value);
        return this;
    }

    /**
     * 添加‘!=’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForNotEq(String property, Object value) {
        addConditionParam(property, Constants.NE_SF, value);
        return this;
    }

    /**
     * 添加‘>=’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForGe(String property, Object value) {
        addConditionParam(property, Constants.GE_SF, value);
        return this;
    }

    /**
     * 添加‘>’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForGt(String property, Object value) {
        addConditionParam(property, Constants.GT_SF, value);
        return this;
    }

    /**
     * 添加‘<’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForLt(String property, Object value) {
        addConditionParam(property, Constants.LT_SF, value);
        return this;
    }

    /**
     * 添加‘<=’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForLe(String property, Object value) {
        addConditionParam(property, Constants.LE_SF, value);
        return this;
    }

    /**
     * 添加‘in’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForIn(String property, List<Object> value) {
        addConditionParam(property, Constants.IN_SF, value);
        return this;
    }

    /**
     * 添加‘not in’的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForNotIn(String property, List<Object> value) {
        addConditionParam(property, Constants.NOTIN_SF, value);
        return this;
    }

    /**
     * 添加‘like aa%’类型的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForStartWith(String property, String value) {
        addConditionParam(property, Constants.SW_SF, value);
        return this;
    }

    /**
     * 添加‘like %aa’类型的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForEndWith(String property, String value) {
        addConditionParam(property, Constants.EW_SF, value);
        return this;
    }

    /**
     * 添加‘like %aa%’类型的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForContain(String property, String value) {
        addConditionParam(property, Constants.CONS_SF, value);
        return this;
    }

    /**
     * 添加‘is null’类型的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForEmpty(String property) {
        addConditionParam(property, Constants.EMPTY_SF, null);
        return this;
    }

    /**
     * 添加‘is not null’类型的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForNotEmpty(String property) {
        addConditionParam(property, Constants.NOTEMPTY_SF, null);
        return this;
    }

    /**
     * 添加‘between and’类型的查询条件，应该在condition语句或or_condition语句之后调用此方法
     * @param property 字段或别名，如果有别名则必须使用别名
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addConditionParamForBt(String property, List<Object> value) {
        addConditionParam(property, Constants.BT_SF, value);
        return this;
    }

    /**
     * 构建查询条件的工具方法
     * @param property  字段或别名，如果有别名则必须使用别名
     * @param op 比较条件
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @param value 目标值
     */
    private void addConditionParam(String property, String op, Object value) {
        if(jPSQLModel.getQueryConditions().isEmpty()) {
            throw new JPQLModelException("当前不存在condition()语句或or_condition()语句，无法使用addConditionParam()语句");
        }
        JPSQLModel.QueryCondition qc = new JPSQLModel.QueryCondition();
        Map<String, Object> pm = jPSQLModel.getQueryConditions().get(jPSQLModel.getQueryConditions().size() - 1).getQueryParams();
        op = StringUtils.isEmpty(op) ? "" : op;
        pm.put(property + op, value);
    }

    /**
     * 添加分组条件
     * @param property 分组字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addGroup(String property) {
        jPSQLModel.getGroups().add(property);
        return this;
    }

    /**
     * 添加升序条件
     * @param property 排序字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addOrderAsc(String property) {
        JPSQLModel.QueryOrder o = new JPSQLModel.QueryOrder();
        o.setName(property);
        o.setType(true);
        jPSQLModel.getOrders().add(o);
        return this;
    }

    /**
     * 添加降序序条件
     * @param property 排序字段
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用
     */
    public JPSQLModelBuilder addOrderDesc(String property) {
        JPSQLModel.QueryOrder o = new JPSQLModel.QueryOrder();
        o.setName(property);
        o.setType(false);
        jPSQLModel.getOrders().add(o);
        return this;
    }

    /**
     * 构建having语句
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder having() {
        if(!jPSQLModel.getHavingConditions().isEmpty()) {
            throw new JPQLModelException("已经存在having()语句，如果你想使用or逻辑，请使用or_having()语句");
        }
        JPSQLModel.HavingCondition hc = new JPSQLModel.HavingCondition();
        jPSQLModel.getHavingConditions().add(hc);
        return this;
    }

    /**
     * 构建having语句中的or语句
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder or_having() {
        if(jPSQLModel.getHavingConditions().isEmpty()) {
            throw new JPQLModelException("当前不存在having()语句，无法使用or_having()语句");
        }
        JPSQLModel.HavingCondition hc = new JPSQLModel.HavingCondition();
        jPSQLModel.getHavingConditions().add(hc);
        return this;
    }

    /**
     * 添加‘=’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForEq(String name, JPSQLModel.FunctionType funcType, Object value) {
        addHavingParam(name, null, funcType, value);
        return this;
    }

    /**
     * 添加‘!=’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForNe(String name, JPSQLModel.FunctionType funcType, Object value) {
        addHavingParam(name, Constants.NE_SF, funcType, value);
        return this;
    }

    /**
     * 添加‘>=’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForGe(String name, JPSQLModel.FunctionType funcType, Object value) {
        addHavingParam(name, Constants.GE_SF, funcType, value);
        return this;
    }

    /**
     * 添加‘>’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForGt(String name, JPSQLModel.FunctionType funcType, Object value) {
        addHavingParam(name, Constants.GT_SF, funcType, value);
        return this;
    }

    /**
     * 添加‘<=’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForLe(String name, JPSQLModel.FunctionType funcType, Object value) {
        addHavingParam(name, Constants.LE_SF, funcType, value);
        return this;
    }

    /**
     * 添加‘<’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForLt(String name, JPSQLModel.FunctionType funcType, Object value) {
        addHavingParam(name, Constants.LT_SF, funcType, value);
        return this;
    }

    /**
     * 添加‘between and ’having条件
     * @param name 字段名称，应使用字段名称而非别名
     * @param funcType 聚合函数
     * @param value 目标值
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @return 构建器本身，以便支持流式调用,只能存在一个having语句
     */
    public JPSQLModelBuilder addHavingParamForBt(String name, JPSQLModel.FunctionType funcType, List<Object> value) {
        addHavingParam(name, Constants.BT_SF, funcType, value);
        return this;
    }

    /**
     * 构建having语句的工具方法
     * @param name 字段名称
     * @param op 比较类型
     * @param funcType 聚合函数
     * @author zhangrb
     * @user all
     * @date 2019-08-26
     * @param value 目标值
     */
    private void addHavingParam(String name, String op, JPSQLModel.FunctionType funcType, Object value) {
        if(jPSQLModel.getHavingConditions().isEmpty()) {
            throw new JPQLModelException("当前不存在having()语句或or_having()语句，无法使用addHavingParam()语句");
        }
        JPSQLModel.HavingParam hp = new JPSQLModel.HavingParam();
        hp.setFuncType(funcType);
        hp.setName(name);
        hp.setValue(value);
        hp.setOp(op);
        jPSQLModel.getHavingConditions().get(jPSQLModel.getHavingConditions().size() - 1).getHavingParams().add(hp);
    }

    /**
     * 返回构建完成之后的JPSQLModel模型
     * @author zhangrb
     * @user user
     * @date 2018-8-22
     * @return JPSQLModel模型
     */
    public JPSQLModel get() {
        return jPSQLModel;
    }
}
